

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>OpenCV Image Processing (Python) &mdash; Industrial Training  documentation</title>
  

  
  

  

  
  
    

  

  
  
    <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  

  
    <link rel="stylesheet" href="../../_static/override.css" type="text/css" />
  

  
        <link rel="index" title="Index"
              href="../../genindex.html"/>
        <link rel="search" title="Search" href="../../search.html"/>
    <link rel="top" title="Industrial Training  documentation" href="../../index.html"/>
        <link rel="next" title="Documentation Generation" href="../session6/Documentation-Generation.html"/>
        <link rel="prev" title="Building a Simple PCL Interface for Python" href="Simple-PCL-Interface-for-Python.html"/> 

  
  <script src="../../_static/js/modernizr.min.js"></script>

</head>

<body class="wy-body-for-nav" role="document">
  
  <script src="../../_static/js/clipboard.min.js"></script>

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-nav-search">
        

        
          <a href="../../index.html" class="icon icon-home">
        

          ROS-Industrial Training Material<br/>kinetic

        
        </a>

        
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

        
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
        
          
          
              <ul>
<li class="toctree-l1"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html">PC Setup</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html#virtual-machine-configuration-recommended">Virtual Machine Configuration (<strong>Recommended</strong>)</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html#limitations-of-virtual-box">Limitations of Virtual Box</a></li>
<li class="toctree-l3"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html#common-vm-issues">Common VM Issues</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html#direct-linux-pc-configuration-not-recommended">Direct Linux PC Configuration (<strong>NOT Recommended</strong>)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../setup/PC-Setup---ROS-Kinetic.html#configuration-check">Configuration Check</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference external" href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-096-introduction-to-c-january-iap-2011/assignments/">MIT Introduction to C++</a></li>
<li class="toctree-l1"><a class="reference external" href="http://mindview.net/Books/TICPP/ThinkingInCPP2e.html">Bruce Eckel Thinking in C++</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/Navigating-the-Ubuntu-GUI.html">Exercise 0.1 - Intro to Ubuntu GUI</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Navigating-the-Ubuntu-GUI.html#task-0-presentation-slides">Task 0: Presentation Slides</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Navigating-the-Ubuntu-GUI.html#task-1-familiarize-yourself-with-the-ubuntu-desktop">Task 1: Familiarize Yourself with the Ubuntu Desktop</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Navigating-the-Ubuntu-GUI.html#task-2-open-and-inspect-an-application">Task 2: Open and Inspect an Application</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Navigating-the-Ubuntu-GUI.html#task-3-start-an-application-pin-it-to-the-launcher-bar">Task 3: Start an Application &amp; Pin it to the Launcher Bar</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/Exploring-the-Linux-File-System.html">Exercise 0.2 - The Linux File System</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Exploring-the-Linux-File-System.html#using-the-file-browser-to-navigate">Using the File Browser to Navigate</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/Exploring-the-Linux-File-System.html#making-changes">Making Changes</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../prerequisites/Exploring-the-Linux-File-System.html#copying-moving-and-removing-files">Copying, Moving, and Removing Files</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html">Starting the Terminal</a></li>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#navigating-directories-and-listing-files">Navigating Directories and Listing Files</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#prepare-your-environment">Prepare your environment</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#ls-command">ls Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#pwd-and-cd-commands"><code class="docutils literal"><span class="pre">pwd</span></code> and <code class="docutils literal"><span class="pre">cd</span></code> Commands</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#altering-files">Altering Files</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#mv-command">mv Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#cp-command">cp Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#rm-command">rm Command</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#mkdir-command">mkdir Command</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#job-management">Job management</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#stopping-jobs">Stopping Jobs</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#stopping-out-of-control-jobs">Stopping “Out of Control” Jobs</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#showing-process-and-memory-usage">Showing Process and Memory usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#editing-text-and-other-gui-commands">Editing Text (and Other GUI Commands)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../prerequisites/The-Linux-Terminal.html#running-commands-as-root">Running Commands as Root</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../session1/ROS-Setup.html">Exercise 1.0 - ROS Setup</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session1/ROS-Setup.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/ROS-Setup.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/ROS-Setup.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/ROS-Setup.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/ROS-Setup.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session1/ROS-Setup.html#setup-bashrc">Setup ~/.bashrc</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/ROS-Setup.html#starting-roscore">Starting roscore</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html">Exercise 1.1 - Create a Workspace</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session1/Create-Catkin-Workspace.html#create-a-catkin-workspace">Create a Catkin Workspace</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session1/Installing-Existing-Packages.html">Exercise 1.2 - Installing Packages</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#install-package-from-apt-repository">Install Package from apt Repository</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Installing-Existing-Packages.html#download-and-build-a-package-from-source">Download and Build a Package from Source</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html">Exercise 1.3 - Packages and Nodes</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#create-a-package">Create a Package</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#stop-we-ll-go-through-a-few-more-lecture-slides-before-continuing-this-exercise">STOP!  We’ll go through a few more lecture slides before continuing this exercise.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#create-a-node">Create a Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#run-a-node">Run a Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Creating-a-ROS-Package-and-Node.html#challenge">Challenge</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session1/Topics-and-Messages.html">Exercise 1.4 - Topics and Messages</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session1/Topics-and-Messages.html#add-the-fake-ar-publisher-package-as-a-dependency">Add the fake_ar_publisher Package as a Dependency</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session1/Topics-and-Messages.html#run-a-publisher-node">Run a Publisher Node</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../session1/Topics-and-Messages.html#create-a-subscriber-node">Create a Subscriber Node</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../session2/Services.html">Exercise 2.0 - Services</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session2/Services.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Services.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Services.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Services.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Services.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session2/Services.html#create-service-definition">Create Service Definition</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session2/Services.html#service-server">Service Server</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session2/Services.html#service-client">Service Client</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session2/Services.html#use-new-service">Use New Service</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session2/Actions.html">Exercise 2.1 - Actions</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session2/Actions.html#ros-tutorials-for-c-action-client-server-usage">ROS Tutorials for C++ Action Client/Server usage</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session2/Launch-Files.html">Exercise 2.2 - Launch Files</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session2/Launch-Files.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Launch-Files.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Launch-Files.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Launch-Files.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Launch-Files.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session2/Parameters.html">Exercise 2.3 - Parameters</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session2/Parameters.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Parameters.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Parameters.html#further-information-and-resource">Further Information and Resource</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Parameters.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session2/Parameters.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../session3/Intro-to-URDF.html">Exercise 3.0 - Intro to URDF</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session3/Intro-to-URDF.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Intro-to-URDF.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Intro-to-URDF.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Intro-to-URDF.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Intro-to-URDF.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session3/Workcell-XACRO.html">Exercise 3.1 - Workcell XACRO</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session3/Workcell-XACRO.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Workcell-XACRO.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Workcell-XACRO.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Workcell-XACRO.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Workcell-XACRO.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html">Exercise 3.2 - Transforms using TF</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Coordinate-Transforms-using-TF.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html">Exercise 3.3 - Build a MoveIt! Package</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Build-a-Moveit!-Package.html#using-moveit-with-physical-hardware">Using MoveIt! with Physical Hardware</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session3/Motion-Planning-RVIZ.html">Exercise 3.4 - Motion Planning using RViz</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session3/Motion-Planning-RVIZ.html#launch-the-planning-environment">Launch the Planning Environment</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Motion-Planning-RVIZ.html#plugin-display-options">Plugin Display Options</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Motion-Planning-RVIZ.html#basic-motion">Basic Motion</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session3/Motion-Planning-RVIZ.html#beyond-the-basics">Beyond the Basics</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../session4/Motion-Planning-CPP.html">Exercise 4.0 - Motion Planning using C++</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session4/Motion-Planning-CPP.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Motion-Planning-CPP.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Motion-Planning-CPP.html#further-information-and-resources">3. Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Motion-Planning-CPP.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Motion-Planning-CPP.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session4/Descartes-Path-Planning.html">Exercise 4.1 - Intro to Descartes</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#setup-workspace">Setup workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#complete-descartes-node">Complete Descartes Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#update-workcell-node">Update Workcell Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#test-full-application">Test Full Application</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Descartes-Path-Planning.html#hints-and-help">Hints and Help</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session4/Introduction-to-Perception.html">Exercise 4.2 - Intro to Perception</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session4/Introduction-to-Perception.html#point-cloud-data-file">Point Cloud Data File</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Introduction-to-Perception.html#display-the-point-cloud-in-rviz">Display the point cloud in RViz</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session4/Introduction-to-Perception.html#experiment-with-pcl">Experiment with PCL</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#downsample-the-point-cloud-using-the-pcl-voxel-grid">Downsample the point cloud using the pcl_voxel_grid.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#extracting-the-table-surface-from-point-cloud-using-the-pcl-sac-segmentation-plane">Extracting the table surface from point cloud using the pcl_sac_segmentation_plane.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#extracting-the-largest-cluster-on-the-table-from-point-cloud-using-the-pcl-sac-segmentation-plane">Extracting the largest cluster on the table from point cloud using the pcl_sac_segmentation_plane.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#remove-outliers-from-the-cloud-using-the-pcl-outlier-removal">Remove outliers from the cloud using the pcl_outlier_removal.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#compute-the-normals-for-each-point-in-the-point-cloud-using-the-pcl-normal-estimation">Compute the normals for each point in the point cloud using the pcl_normal_estimation.</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session4/Introduction-to-Perception.html#mesh-a-point-cloud-using-the-marching-cubes-reconstruction">Mesh a point cloud using the marching cubes reconstruction.</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../demo1/index.html">      Demo 1 - Perception-Driven Manipulation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Introduction.html">Demo 1.0 - Introduction</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Introduction.html#goal">Goal</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Introduction.html#objectives">Objectives</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Inspect-the-package.html">Demo 1.1 - Inspect the &quot;pick_and_place_exercise&quot; Package</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#acquire-and-initialize-the-workspace">Acquire and initialize the Workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#download-source-dependencies">Download source dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#download-debian-dependencies">Download debian dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#build-your-workspace">Build your workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#source-the-workspace">Source the workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#locate-and-navigate-into-the-package">Locate and navigate into the package</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#look-into-each-file-in-the-launch-directory">Look into each file in the launch directory</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#look-into-the-config-directory">Look into the config directory</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Inspect-the-package.html#look-into-the-src-directory">Look into the src directory</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Package-Setup.html">Demo 1.2 - Package Setup</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Package-Setup.html#build-package-dependencies">Build Package Dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Package-Setup.html#import-package-into-qtcreator">Import Package into QTCreator</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Package-Setup.html#open-the-main-thread-source-file">Open the Main Thread Source File</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Bring-up-ROS-system-in-simulation-mode.html">Demo 1.3 - Start in Simulation Mode</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Bring-up-ROS-system-in-simulation-mode.html#run-setup-launch-file-in-simulation-mode-simulated-robot-and-sensor">Run setup launch file in simulation mode (simulated robot and sensor)</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Bring-up-ROS-system-in-simulation-mode.html#setup-for-real-sensor-and-simulated-robot">Setup for real sensor and simulated robot</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Bring-up-ROS-system-in-simulation-mode.html#setup-for-real-robot-and-simulated-sensor-data">Setup for real robot and simulated sensor data</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Bring-up-ROS-system-in-simulation-mode.html#setup-for-real-robot-and-real-sensor">Setup for real robot and real sensor</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Initialization-and-global-variables.html">Demo 1.4 - Initialization and Global Variables</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Initialization-and-global-variables.html#application-variables">Application Variables</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Initialization-and-global-variables.html#node-initialization">Node Initialization</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Move-arm-to-wait-position.html">Demo 1.5 - Move Arm to Wait Position</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Move-arm-to-wait-position.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Move-arm-to-wait-position.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Move-arm-to-wait-position.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Move-arm-to-wait-position.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Open-gripper.html">Demo 1.6 - Open Gripper</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Open-gripper.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Open-gripper.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Open-gripper.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Open-gripper.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Detect-box-pick-point.html">Demo 1.7 - Detect Box Pick Point</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Detect-box-pick-point.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Detect-box-pick-point.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Detect-box-pick-point.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Detect-box-pick-point.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Create-pick-moves.html">Demo 1.8 - Create Pick Moves</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-pick-moves.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-pick-moves.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-pick-moves.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-pick-moves.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Pick-up-box.html">Demo 1.9 - Pick Up Box</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Pick-up-box.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Pick-up-box.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Pick-up-box.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Pick-up-box.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Create-place-moves.html">Demo 1.10 - Create Place Moves</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-place-moves.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-place-moves.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-place-moves.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Create-place-moves.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo1/Place-box.html">Demo 1.11 - Place Box</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Place-box.html#locate-function">Locate Function</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Place-box.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Place-box.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo1/Place-box.html#api-references">API References</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../demo2/index.html">Demo 2 - Descartes Planning and Execution</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Introduction.html">Demo 2.0 - Introduction</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Introduction.html#goal">Goal</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Introduction.html#objectives">Objectives</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Application-Structure.html">Demo 2.1 - Application Structure</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#acquire-and-initialize-the-workspace">Acquire and initialize the Workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#download-source-dependencies">Download source dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#download-debian-dependencies">Download debian dependencies</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#build-your-workspace">Build your workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#source-the-workspace">Source the workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#list-all-the-packages-in-the-application">List All the Packages in the Application</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#the-plan-and-run-package">The <code class="docutils literal"><span class="pre">plan_and_run</span></code> package</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#main-application-source-file">Main Application Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#the-demoapplication-class">The DemoApplication Class</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Application-Structure.html#application-launch-file">Application Launch File</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/General-Instructions.html">Demo 2.2 - General Instructions</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/General-Instructions.html#main-objective">Main Objective</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/General-Instructions.html#complete-exercises">Complete Exercises</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/General-Instructions.html#run-demo-in-simulation-mode">Run Demo in Simulation Mode</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/General-Instructions.html#run-demo-on-the-real-robot">Run Demo on the Real Robot</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Load-Parameters.html">Demo 2.3 - Load Parameters</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Load-Parameters.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Load-Parameters.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Load-Parameters.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Load-Parameters.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Initialize-ROS.html">Demo 2.4 - Initialize ROS</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-ROS.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-ROS.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-ROS.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-ROS.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Initialize-Descartes.html">Demo 2.5 - Initialize Descartes</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-Descartes.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-Descartes.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-Descartes.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Initialize-Descartes.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Move-Home.html">Demo 2.6 - Move Home</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Move-Home.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Move-Home.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Move-Home.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Move-Home.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Generate-a-Semi-Constrained-Trajectory.html">Demo 2.7 - Generate a Semi-Constrained Trajectory</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Generate-a-Semi-Constrained-Trajectory.html#locate-exercise-source-file">Locate exercise source file</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Generate-a-Semi-Constrained-Trajectory.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Generate-a-Semi-Constrained-Trajectory.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Generate-a-Semi-Constrained-Trajectory.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Plan-a-robot-path.html">Demo 2.8 - Plan a Robot Path</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Plan-a-robot-path.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Plan-a-robot-path.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Plan-a-robot-path.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Plan-a-robot-path.html#api-references">API References</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../demo2/Run-a-robot-path.html">Demo 2.9 - Run a Robot Path</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Run-a-robot-path.html#locate-exercise-source-file">Locate Exercise Source File</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Run-a-robot-path.html#complete-code">Complete Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Run-a-robot-path.html#build-code-and-run">Build Code and Run</a></li>
<li class="toctree-l3"><a class="reference internal" href="../demo2/Run-a-robot-path.html#api-references">API References</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html">Exercise 5.0 - Advanced Descartes Path Planning</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#reference-example">Reference Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#setup-workspace">Setup workspace</a></li>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#update-your-workcell-xacro-file">Update your workcell.xacro file.</a></li>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#add-new-planning-group-to-your-moveit-config-package">Add new planning group to your moveit_config package.</a></li>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#complete-advanced-descartes-node">Complete Advanced Descartes Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#update-the-setup-launch-file">Update the setup.launch file.</a></li>
<li class="toctree-l3"><a class="reference internal" href="Advanced-Descartes-Path-Planning.html#test-full-application">Test Full Application</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Building-a-Perception-Pipeline.html">Exercise 5.1 - Building a Perception Pipeline</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Building-a-Perception-Pipeline.html#prepare-new-workspace">Prepare New Workspace:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Building-a-Perception-Pipeline.html#intro-review-existing-code">Intro (Review Existing Code)</a></li>
<li class="toctree-l2"><a class="reference internal" href="Building-a-Perception-Pipeline.html#primary-task-filling-in-the-blanks">Primary Task: Filling in the blanks</a><ul>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#implement-voxel-filter">Implement Voxel Filter</a><ul>
<li class="toctree-l4"><a class="reference internal" href="Building-a-Perception-Pipeline.html#viewing-results">Viewing Results</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#implement-pass-through-filters">Implement Pass-through Filters</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#plane-segmentation">Plane Segmentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#euclidean-cluster-extraction-optional-but-recommended">Euclidean Cluster Extraction (optional, but recommended)</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#create-a-cropbox-filter">Create a CropBox Filter</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#create-a-statistical-outlier-removal">Create a Statistical Outlier Removal</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#create-a-broadcast-transform">Create a Broadcast Transform</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#create-a-polygonal-segmentation">Create a Polygonal Segmentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="Building-a-Perception-Pipeline.html#write-a-launch-file">Write a launch file</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Introduction-to-STOMP.html">Exercise 5.2 - Introduction to STOMP</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Introduction-to-STOMP.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="Introduction-to-STOMP.html#information-and-resources">Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="Introduction-to-STOMP.html#objectives">Objectives</a></li>
<li class="toctree-l2"><a class="reference internal" href="Introduction-to-STOMP.html#setup">Setup</a></li>
<li class="toctree-l2"><a class="reference internal" href="Introduction-to-STOMP.html#add-stomp">Add STOMP</a><ul>
<li class="toctree-l3"><a class="reference internal" href="Introduction-to-STOMP.html#run-moveit-with-stomp">Run MoveIt! with STOMP</a></li>
<li class="toctree-l3"><a class="reference internal" href="Introduction-to-STOMP.html#explore-stomp">Explore STOMP</a></li>
<li class="toctree-l3"><a class="reference internal" href="Introduction-to-STOMP.html#configure-stomp">Configure STOMP</a></li>
<li class="toctree-l3"><a class="reference internal" href="Introduction-to-STOMP.html#more-info-on-the-stomp-parameters">More info on the STOMP parameters</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html">Exercise 5.3 - Simple PCL Interface for Python</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#prepare-new-workspace">Prepare New Workspace:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#intro-review-existing-code">Intro (Review Existing Code)</a><ul>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#create-a-python-package">Create a Python Package</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#creating-setup-py">Creating setup.py</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#publishing-the-point-cloud">Publishing the Point Cloud</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#implement-a-voxel-filter">Implement a Voxel Filter</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#viewing-results">Viewing Results</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#implement-pass-through-filters">Implement Pass-Through Filters</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#plane-segmentation">Plane Segmentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#euclidian-cluster-extraction">Euclidian Cluster Extraction</a></li>
<li class="toctree-l3"><a class="reference internal" href="Simple-PCL-Interface-for-Python.html#future-study">Future Study</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Exercise 5.4 - OpenCV Image Processing (Python)</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="#further-information-and-resources">Further Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="#problem-statement">Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="#implementation">Implementation</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#create-package">Create package</a></li>
<li class="toctree-l3"><a class="reference internal" href="#create-an-image-publisher">Create an Image Publisher</a></li>
<li class="toctree-l3"><a class="reference internal" href="#create-the-detect-pump-image-processing-node">Create the Detect_Pump Image-Processing Node</a></li>
<li class="toctree-l3"><a class="reference internal" href="#challenge-exercises">Challenge Exercises</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../session6/Documentation-Generation.html">Exercise 6.0 - Documentation Generation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session6/Documentation-Generation.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Documentation-Generation.html#information-and-resources">Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Documentation-Generation.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Documentation-Generation.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session6/Documentation-Generation.html#annotate-the-source-code">Annotate the Source Code</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Documentation-Generation.html#generate-documentation">Generate documentation</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Documentation-Generation.html#view-the-documentation">View the Documentation</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session6/Unit-Testing.html">Exercise 6.1 - Unit Testing</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session6/Unit-Testing.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Unit-Testing.html#information-and-resources">Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Unit-Testing.html#problem-statement">Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Unit-Testing.html#guidance">Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session6/Unit-Testing.html#create-the-unit-test-frame-work">Create the unit test frame work</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Unit-Testing.html#add-stock-publisher-tests">Add stock publisher tests</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Unit-Testing.html#write-specific-unit-tests">Write specific unit tests</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html">Exercise 6.2 - Using rqt tools for Analysis</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#information-and-resources">Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#problem-statement">Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#guidance">Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#rqt-graph-view-node-interaction"><code class="docutils literal"><span class="pre">rqt_graph</span></code>: view node interaction</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#rqt-console-view-messages"><code class="docutils literal"><span class="pre">rqt_console</span></code>: view messages:</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Using-rqt-tools-for-analysis.html#rqt-plot-view-data-plots"><code class="docutils literal"><span class="pre">rqt_plot</span></code>: view data plots</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html">Exercise 6.3 - ROS Style Guide and ros_lint</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#motivation">Motivation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#information-and-resources">Information and Resources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#scan-n-plan-application-problem-statement">Scan-N-Plan Application: Problem Statement</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#scan-n-plan-application-guidance">Scan-N-Plan Application: Guidance</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#configure-package">Configure Package</a></li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Style-Guide-and-ros_lint.html#run-roslint">Run roslint</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../session6/Docker-AWS.html">Exercise 6.4 - Introduction to ROS with Docker and Amazon Web Services (AWS)</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../session6/Docker-AWS.html#demo-1-run-front-end-gazebo-host-and-back-end-in-docker">Demo #1 - Run front-end Gazebo host and back-end in Docker</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../session6/Docker-AWS.html#setup-workspace">Setup workspace</a><ul>
<li class="toctree-l4"><a class="reference internal" href="../session6/Docker-AWS.html#front-end-run-on-host-and-only-contains-gui">Front-end (run on host and only contains gui)</a></li>
<li class="toctree-l4"><a class="reference internal" href="../session6/Docker-AWS.html#back-end-run-in-container">Back-end (run in container)</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="../session6/Docker-AWS.html#running-the-demo">Running the Demo</a><ul>
<li class="toctree-l4"><a class="reference internal" href="../session6/Docker-AWS.html#run-the-front-end">Run the front-end</a></li>
<li class="toctree-l4"><a class="reference internal" href="../session6/Docker-AWS.html#run-the-backend">Run the backend</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Docker-AWS.html#demo-2-run-front-end-on-a-web-server-and-back-end-in-docker">Demo #2 - Run front-end on a web-server and back-end in docker</a></li>
<li class="toctree-l2"><a class="reference internal" href="../session6/Docker-AWS.html#demo-3-robot-web-tools">Demo #3 Robot Web Tools</a></li>
</ul>
</li>
</ul>

          
        
      </div>
      &nbsp;
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../../index.html">Industrial Training</a>
      </nav>

      
      <div class="wy-nav-content">

        <div class="header-override">
          <a href="http://rosindustrial.org">
            <img src="../../_static/logo.jpg"/>
          </a>
          <p>
            <a href="http://rosindustrial.org">ROS-Industrial Website</a>|<a href="http://rosindustrial.org/news">Blog</a>
          </p>
        </div>

        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li class="wy-breadcrumbs-aside">
      
        
          <a href="https://github.com/ros-industrial/industrial_training/blob/kinetic/gh_pages/_source/session5/OpenCV-in-Python.md" class="fa fa-github"> Edit on GitHub</a>
        
      
    </li>
    <li><a href="../../index.html">Docs</a> &raquo;</li>
      
    <li>OpenCV Image Processing (Python)</li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             <div class="admonition note">
               <p class="first admonition-title">The code used in this tutorial is available!</p>
               <p class="last">Code can be found at <a href = "https://github.com/ros-industrial/industrial_training">industrial_training repository</a> in gh_pages folder. Use kinetic branch.</p>
             </div>

            
  <div class="section" id="opencv-image-processing-python">
<span id="opencv-image-processing-python"></span><h1>OpenCV Image Processing (Python)<a class="headerlink" href="#opencv-image-processing-python" title="Permalink to this headline">¶</a></h1>
<p>In this exercise, we will gain familiarity with both OpenCV and Python, through a simple 2D image-processing application.</p>
<div class="section" id="motivation">
<span id="motivation"></span><h2>Motivation<a class="headerlink" href="#motivation" title="Permalink to this headline">¶</a></h2>
<p>OpenCV is a mature, stable library for 2D image processing, used in a wide variety of applications.  Much of ROS makes use of 3D sensors and point-cloud data, but there are still many applications that use traditional 2D cameras and image processing.</p>
<p>This tutorial uses python to build the image-processing pipeline.  Python is a good choice for this application, due to its ease of rapid prototyping and existing bindings to the OpenCV library.</p>
</div>
<div class="section" id="further-information-and-resources">
<span id="further-information-and-resources"></span><h2>Further Information and Resources<a class="headerlink" href="#further-information-and-resources" title="Permalink to this headline">¶</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://opencv.org/">OpenCV Website</a></li>
<li><a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/refman.html">OpenCV API</a></li>
<li><a class="reference external" href="https://docs.opencv.org/3.4.2/d6/d00/tutorial_py_root.html">OpenCV Python Tutorials</a></li>
<li><a class="reference external" href="http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython">ROS cv_bridge package (Python)</a></li>
<li><a class="reference external" href="http://wiki.ros.org/rospy_tutorials/Tutorials/WritingPublisherSubscriber">Writing a Publisher and Subscriber (Python)</a></li>
<li><a class="reference external" href="http://docs.ros.org/kinetic/api/sensor_msgs/html/msg/Image.html">sensor_msgs/Image</a></li>
</ul>
</div>
<div class="section" id="problem-statement">
<span id="problem-statement"></span><h2>Problem Statement<a class="headerlink" href="#problem-statement" title="Permalink to this headline">¶</a></h2>
<p>In this exercise, you will create a new node to determine the angular pose of a pump housing using the OpenCV image processing library.  The pump’s orientation is computed using a series of processing steps to extract and compare geometry features:</p>
<ol class="simple">
<li>Resize the image (to speed up processing)</li>
<li>Threshold the image (convert to black &amp; white)</li>
<li>Locate the pump’s outer housing (circle-finding)</li>
<li>Locate the piston sleeve locations (blob detection)</li>
<li>Estimate primary axis using bounding box</li>
<li>Determine orientation using piston sleeve locations</li>
<li>Calculate the axis orientation relative to a reference (horizontal) axis</li>
</ol>
<p><img alt="pump images" src="https://aeswiki.datasys.swri.edu/rositraining/indigo/Exercises/2A.2?action=AttachFile&amp;do=get&amp;target=pump_images.png" /></p>
</div>
<div class="section" id="implementation">
<span id="implementation"></span><h2>Implementation<a class="headerlink" href="#implementation" title="Permalink to this headline">¶</a></h2>
<div class="section" id="create-package">
<span id="create-package"></span><h3>Create package<a class="headerlink" href="#create-package" title="Permalink to this headline">¶</a></h3>
<p>This exercise uses a single package that can be placed in any catkin workspace. The examples below will use the <code class="docutils literal"><span class="pre">~/catkin_ws</span></code> workspace from earlier exercises.</p>
<ol>
<li><p class="first">Create a new <code class="docutils literal"><span class="pre">detect_pump</span></code> package to contain the new python nodes we’ll be making:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nb">cd</span> ~/catkin_ws/src
catkin create pkg detect_pump --catkin-deps rospy cv_bridge
</pre></div>
</div>
<ul class="simple">
<li>all ROS packages depend on <code class="docutils literal"><span class="pre">rospy</span></code></li>
<li>we’ll use <code class="docutils literal"><span class="pre">cv_bridge</span></code> to convert between ROS’s standard Image message and OpenCV’s Image object</li>
<li><code class="docutils literal"><span class="pre">cv_bridge</span></code> also automatically brings in dependencies on the relevant OpenCV modules</li>
</ul>
</li>
<li><p class="first">Create a python module for this package:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nb">cd</span> detect_pump
mkdir nodes
</pre></div>
</div>
<ul class="simple">
<li>For a simple package such as this, the <a class="reference external" href="http://docs.ros.org/kinetic/api/catkin/html/howto/format2/installing_python.html">Python Style Guide</a> recommends this simplified package structure.</li>
<li>More complex packages (e.g. with exportable modules, msg/srv defintions, etc.) should us a more complex package structure, with an <code class="docutils literal"><span class="pre">__init__.py</span></code> and <code class="docutils literal"><span class="pre">setup.py</span></code>.<ul>
<li>reference <a class="reference external" href="http://docs.ros.org/kinetic/api/catkin/html/howto/format2/installing_python.html">Installing Python Scripts</a></li>
<li>reference <a class="reference external" href="http://docs.ros.org/api/catkin/html/user_guide/setup_dot_py.html">Handling setup.py</a></li>
</ul>
</li>
</ul>
</li>
</ol>
</div>
<div class="section" id="create-an-image-publisher">
<span id="create-an-image-publisher"></span><h3>Create an Image Publisher<a class="headerlink" href="#create-an-image-publisher" title="Permalink to this headline">¶</a></h3>
<p>The first node will read in an image from a file and publish it as a ROS <a class="reference external" href="http://docs.ros.org/kinetic/api/sensor_msgs/html/msg/Image.html">Image</a> message on the <code class="docutils literal"><span class="pre">image</span></code> topic.</p>
<ul class="simple">
<li>Note: ROS already contains an <code class="docutils literal"><span class="pre">image_publisher</span></code> package/node that performs this function, but we will duplicate it here to learn about ROS Publishers in Python.</li>
</ul>
<ol>
<li><p class="first">Create a new python script for our image-publisher node (<code class="docutils literal"><span class="pre">nodes/image_pub.py</span></code>).  Fill in the following template for a skeleton ROS python node:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="ch">#!/usr/bin/env python</span>
<span class="kn">import</span> <span class="nn">rospy</span>

<span class="k">def</span> <span class="nf">start_node</span><span class="p">():</span>
    <span class="n">rospy</span><span class="o">.</span><span class="n">init_node</span><span class="p">(</span><span class="s1">&#39;image_pub&#39;</span><span class="p">)</span>
    <span class="n">rospy</span><span class="o">.</span><span class="n">loginfo</span><span class="p">(</span><span class="s1">&#39;image_pub node started&#39;</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">start_node</span><span class="p">()</span>
    <span class="k">except</span> <span class="n">rospy</span><span class="o">.</span><span class="n">ROSInterruptException</span><span class="p">:</span>
        <span class="k">pass</span>
</pre></div>
</div>
</li>
<li><p class="first">Allow execution of the new script file:</p>
<div class="highlight-bash"><div class="highlight"><pre>chmod u+x nodes/image_pub.py
</pre></div>
</div>
</li>
<li><p class="first">Test run the image publisher:</p>
<div class="highlight-bash"><div class="highlight"><pre>roscore
rosrun detect_pump image_pump.py
</pre></div>
</div>
<ul class="simple">
<li>You should see the “node started” message</li>
</ul>
</li>
<li><p class="first">Read the image file to publish, using the filename provided on the command line</p>
<ol>
<li><p class="first">Import the <code class="docutils literal"><span class="pre">sys</span></code> and <code class="docutils literal"><span class="pre">cv2</span></code> (OpenCV) modules:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">cv2</span>
</pre></div>
</div>
</li>
<li><p class="first">Pass the command-line argument into the <code class="docutils literal"><span class="pre">start_node</span></code> function:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">start_node</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="o">...</span>
<span class="n">start_node</span><span class="p">(</span> <span class="n">rospy</span><span class="o">.</span><span class="n">myargv</span><span class="p">(</span><span class="n">argv</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span> <span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>Note the use of <code class="docutils literal"><span class="pre">rospy.myargv()</span></code> to strip out any ROS-specific command-line arguments.</li>
</ul>
</li>
<li><p class="first">In the <code class="docutils literal"><span class="pre">start_node</span></code> function, call the OpenCV <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/imgcodecs/doc/reading_and_writing_images.html#imread">imread</a> function to read the image.  Then use <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/highgui/doc/user_interface.html#imshow">imshow</a> to display it:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">img</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">imread</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="n">cv2</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="s2">&quot;image&quot;</span><span class="p">,</span> <span class="n">img</span><span class="p">)</span>
<span class="n">cv2</span><span class="o">.</span><span class="n">waitKey</span><span class="p">(</span><span class="mi">2000</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Run the node, with the specified image file:</p>
<div class="highlight-bash"><div class="highlight"><pre>rosrun detect_pump image_pub.py ~/industrial_training/exercises/5.4/pump.jpg
</pre></div>
</div>
<ul class="simple">
<li>You should see the image displayed</li>
<li>Comment out the <code class="docutils literal"><span class="pre">imshow</span></code>/<code class="docutils literal"><span class="pre">waitKey</span></code> lines, as we won’t need those any more</li>
<li>Note that you don’t need to run <code class="docutils literal"><span class="pre">catkin</span> <span class="pre">build</span></code> after editing the python file, since no compile step is needed.</li>
</ul>
</li>
</ol>
</li>
<li><p class="first">Convert the image from OpenCV Image object to ROS Image message:</p>
<ol>
<li><p class="first">Import the <code class="docutils literal"><span class="pre">CvBridge</span></code> and <code class="docutils literal"><span class="pre">Image</span></code> (ROS message) modules:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">cv_bridge</span> <span class="kn">import</span> <span class="n">CvBridge</span>
<span class="kn">from</span> <span class="nn">sensor_msgs.msg</span> <span class="kn">import</span> <span class="n">Image</span>
</pre></div>
</div>
</li>
<li><p class="first">Add a call to the CvBridge <a class="reference external" href="https://docs.ros.org/api/cv_bridge/html/python/">cv2_to_imgmsg</a> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">bridge</span> <span class="o">=</span> <span class="n">CvBridge</span><span class="p">()</span>
<span class="n">imgMsg</span> <span class="o">=</span> <span class="n">bridge</span><span class="o">.</span><span class="n">cv2_to_imgmsg</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="s2">&quot;bgr8&quot;</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ol>
</li>
<li><p class="first">Create a ROS publisher to continually publish the Image message on the <code class="docutils literal"><span class="pre">image</span></code> topic.  Use a loop with a 1 Hz throttle to publish the message.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">pub</span> <span class="o">=</span> <span class="n">rospy</span><span class="o">.</span><span class="n">Publisher</span><span class="p">(</span><span class="s1">&#39;image&#39;</span><span class="p">,</span> <span class="n">Image</span><span class="p">,</span> <span class="n">queue_size</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">rospy</span><span class="o">.</span><span class="n">is_shutdown</span><span class="p">():</span>
    <span class="n">pub</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span><span class="n">imgMsg</span><span class="p">)</span>
    <span class="n">rospy</span><span class="o">.</span><span class="n">Rate</span><span class="p">(</span><span class="mf">1.0</span><span class="p">)</span><span class="o">.</span><span class="n">sleep</span><span class="p">()</span>  <span class="c1"># 1 Hz</span>
</pre></div>
</div>
</li>
<li><p class="first">Run the node and inspect the newly-published image message</p>
<ol>
<li><p class="first">Run the node (as before):</p>
<div class="highlight-bash"><div class="highlight"><pre>rosrun detect_pump image_pub.py ~/industrial_training/exercises/5.4/pump.jpg
</pre></div>
</div>
</li>
<li><p class="first">Inspect the message topic using command-line tools:</p>
<div class="highlight-bash"><div class="highlight"><pre>rostopic list
rostopic hz /image
rosnode info /image_pub
</pre></div>
</div>
</li>
<li><p class="first">Inspect the published image using the standalone <a class="reference external" href="http://wiki.ros.org/image_view#image_view.2BAC8-diamondback.image_view">image_view</a> node</p>
<div class="highlight-bash"><div class="highlight"><pre>rosrun image_view image_view
</pre></div>
</div>
</li>
</ol>
</li>
</ol>
</div>
<div class="section" id="create-the-detect-pump-image-processing-node">
<span id="create-the-detect-pump-image-processing-node"></span><h3>Create the Detect_Pump Image-Processing Node<a class="headerlink" href="#create-the-detect-pump-image-processing-node" title="Permalink to this headline">¶</a></h3>
<p>The next node will subscribe to the <code class="docutils literal"><span class="pre">image</span></code> topic and execute a series of processing steps to identify the pump’s orientation relative to the horizontal image axis.</p>
<ol>
<li><p class="first">As before, create a basic ROS python node (<code class="docutils literal"><span class="pre">detect_pump.py</span></code>) and set its executable permissions:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="ch">#!/usr/bin/env python</span>
<span class="kn">import</span> <span class="nn">rospy</span>

<span class="c1"># known pump geometry</span>
<span class="c1">#  - units are pixels (of half-size image)</span>
<span class="n">PUMP_DIAMETER</span> <span class="o">=</span> <span class="mi">360</span>
<span class="n">PISTON_DIAMETER</span> <span class="o">=</span> <span class="mi">90</span>
<span class="n">PISTON_COUNT</span> <span class="o">=</span> <span class="mi">7</span>

<span class="k">def</span> <span class="nf">start_node</span><span class="p">():</span>
    <span class="n">rospy</span><span class="o">.</span><span class="n">init_node</span><span class="p">(</span><span class="s1">&#39;detect_pump&#39;</span><span class="p">)</span>
    <span class="n">rospy</span><span class="o">.</span><span class="n">loginfo</span><span class="p">(</span><span class="s1">&#39;detect_pump node started&#39;</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">start_node</span><span class="p">()</span>
    <span class="k">except</span> <span class="n">rospy</span><span class="o">.</span><span class="n">ROSInterruptException</span><span class="p">:</span>
        <span class="k">pass</span>
</pre></div>
</div>
<div class="highlight-bash"><div class="highlight"><pre>chmod u+x nodes/detect_pump.py
</pre></div>
</div>
<ul class="simple">
<li>Note that we don’t have to edit <code class="docutils literal"><span class="pre">CMakeLists</span></code> to create new build rules for each script, since python does not need to be compiled.</li>
</ul>
</li>
<li><p class="first">Add a ROS subscriber to the <code class="docutils literal"><span class="pre">image</span></code> topic, to provide the source for images to process.</p>
<ol>
<li><p class="first">Import the <code class="docutils literal"><span class="pre">Image</span></code> message header</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sensor_msgs.msg</span> <span class="kn">import</span> <span class="n">Image</span>
</pre></div>
</div>
</li>
<li><p class="first">Above the <code class="docutils literal"><span class="pre">start_node</span></code> function, create an empty callback (<code class="docutils literal"><span class="pre">process_image</span></code>) that will be called when a new Image message is received:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">process_image</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
    <span class="k">pass</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
        <span class="k">print</span> <span class="n">err</span>
</pre></div>
</div>
<ul class="simple">
<li>The try/except error handling will allow our code to continue running, even if there are errors during the processing pipeline.</li>
</ul>
</li>
<li><p class="first">In the <code class="docutils literal"><span class="pre">start_node</span></code> function, create a ROS Subscriber object:</p>
<ul class="simple">
<li>subscribe to the <code class="docutils literal"><span class="pre">image</span></code> topic, monitoring messages of type <code class="docutils literal"><span class="pre">Image</span></code></li>
<li>register the callback function we defined above</li>
</ul>
<div class="highlight-python"><div class="highlight"><pre><span class="n">rospy</span><span class="o">.</span><span class="n">Subscriber</span><span class="p">(</span><span class="s2">&quot;image&quot;</span><span class="p">,</span> <span class="n">Image</span><span class="p">,</span> <span class="n">process_image</span><span class="p">)</span>
<span class="n">rospy</span><span class="o">.</span><span class="n">spin</span><span class="p">()</span>
</pre></div>
</div>
<ul class="simple">
<li>reference: <a class="reference external" href="http://docs.ros.org/kinetic/api/rospy/html/rospy.topics.Subscriber-class.html">rospy.Subscriber</a></li>
<li>reference: <a class="reference external" href="http://docs.ros.org/kinetic/api/rospy/html/rospy-module.html#spin">rospy.spin</a></li>
</ul>
</li>
<li><p class="first">Run the new node and verify that it is subscribing to the topic as expected:</p>
<div class="highlight-bash"><div class="highlight"><pre>rosrun detect_pump detect_pump.py
rosnode info /detect_pump
rqt_graph
</pre></div>
</div>
</li>
</ol>
</li>
<li><p class="first">Convert the incoming <code class="docutils literal"><span class="pre">Image</span></code> message to an OpenCV <code class="docutils literal"><span class="pre">Image</span></code> object and display it
As before, we’ll use the <code class="docutils literal"><span class="pre">CvBridge</span></code> module to do the conversion.</p>
<ol>
<li><p class="first">Import the <code class="docutils literal"><span class="pre">CvBridge</span></code> modules:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">cv_bridge</span> <span class="kn">import</span> <span class="n">CvBridge</span>
</pre></div>
</div>
</li>
<li><p class="first">In the <code class="docutils literal"><span class="pre">process_image</span></code> callback, add a call to the CvBridge <a class="reference external" href="https://docs.ros.org/api/cv_bridge/html/python/">imgmsg_to_cv2</a> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># convert sensor_msgs/Image to OpenCV Image</span>
<span class="n">bridge</span> <span class="o">=</span> <span class="n">CvBridge</span><span class="p">()</span>
<span class="n">orig</span> <span class="o">=</span> <span class="n">bridge</span><span class="o">.</span><span class="n">imgmsg_to_cv2</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="s2">&quot;bgr8&quot;</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>This code (and all other image-processing code) should go inside the <code class="docutils literal"><span class="pre">try</span></code> block, to ensure that processing errors don’t crash the node.</li>
<li>This should replace the placeholder <code class="docutils literal"><span class="pre">pass</span></code> command placed in the <code class="docutils literal"><span class="pre">try</span></code> block earlier</li>
</ul>
</li>
<li><p class="first">Use the OpenCV <code class="docutils literal"><span class="pre">imshow</span></code> method to display the images received.  We’ll create a pattern that can be re-used to show the result of each image-processing step.</p>
<ol>
<li><p class="first">Import the OpenCV <code class="docutils literal"><span class="pre">cv2</span></code> module:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">cv2</span>
</pre></div>
</div>
</li>
<li><p class="first">Add a display helper function above the <code class="docutils literal"><span class="pre">process_image</span></code> callback:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">showImage</span><span class="p">(</span><span class="n">img</span><span class="p">):</span>
    <span class="n">cv2</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="s1">&#39;image&#39;</span><span class="p">,</span> <span class="n">img</span><span class="p">)</span>
    <span class="n">cv2</span><span class="o">.</span><span class="n">waitKey</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Copy the received image to a new “drawImg” variable:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">drawImg</span> <span class="o">=</span> <span class="n">orig</span>
</pre></div>
</div>
</li>
<li><p class="first"><strong>Below</strong> the <code class="docutils literal"><span class="pre">except</span></code> block (outside its scope; at <code class="docutils literal"><span class="pre">process_image</span></code> scope, display the <code class="docutils literal"><span class="pre">drawImg</span></code> variable:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># show results</span>
<span class="n">showImage</span><span class="p">(</span><span class="n">drawImg</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ol>
</li>
<li><p class="first">Run the node and see the received image displayed.</p>
</li>
</ol>
</li>
<li><p class="first">The first step in the image-processing pipeline is to resize the image, to speed up future processing steps.  Add the following code inside the <code class="docutils literal"><span class="pre">try</span></code> block, then rerun the node.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># resize image (half-size) for easier processing</span>
<span class="n">resized</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">resize</span><span class="p">(</span><span class="n">orig</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="n">fx</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">fy</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
<span class="n">drawImg</span> <span class="o">=</span> <span class="n">resized</span>
</pre></div>
</div>
<ul class="simple">
<li>you should see a smaller image being displayed</li>
<li>reference: <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/imgproc/doc/geometric_transformations.html#resize">resize()</a></li>
</ul>
</li>
<li><p class="first">Next, convert the image from color to grayscale.  Run the node to check for errors, but the image will still look the same as previously.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># convert to single-channel image</span>
<span class="n">gray</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">cvtColor</span><span class="p">(</span><span class="n">resized</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">COLOR_BGR2GRAY</span><span class="p">)</span>
<span class="n">drawImg</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">cvtColor</span><span class="p">(</span><span class="n">gray</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">COLOR_GRAY2BGR</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>Even though the original image looks gray, the JPG file, Image message, and <code class="docutils literal"><span class="pre">orig</span></code> OpenCV image are all 3-channel color images.</li>
<li>Many OpenCV functions operate on individual image channels.  Converting an image that appears gray to a “true” 1-channel grayscale image can help avoid confusion further on.</li>
<li>We convert back to a color image for <code class="docutils literal"><span class="pre">drawImg</span></code> so that we can draw colored overlays on top of the image to display the results of later processing steps.</li>
<li>reference: <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor">cvtColor()</a></li>
</ul>
</li>
<li><p class="first">Apply a thresholding operation to turn the grayscale image into a binary image.  Run the node and see the thresholded image.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># threshold grayscale to binary (black &amp; white) image</span>
<span class="n">threshVal</span> <span class="o">=</span> <span class="mi">75</span>
<span class="n">ret</span><span class="p">,</span><span class="n">thresh</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">threshold</span><span class="p">(</span><span class="n">gray</span><span class="p">,</span> <span class="n">threshVal</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">THRESH_BINARY</span><span class="p">)</span>
<span class="n">drawImg</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">cvtColor</span><span class="p">(</span><span class="n">thresh</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">COLOR_GRAY2BGR</span><span class="p">)</span> 
</pre></div>
</div>
<p>You should experiment with the <code class="docutils literal"><span class="pre">threshVal</span></code> paramter to find a value that works best for this image.  Valid values for this parameter lie between [0-255], to match the grayscale pixel intensity range.  Find a value that clearly highlights the pump face geometry.  I found that a value of <code class="docutils literal"><span class="pre">150</span></code> seemed good to me.</p>
<ul class="simple">
<li>reference <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html#threshold">threshold</a></li>
</ul>
</li>
<li><p class="first">Detect the outer pump-housing circle.</p>
<p>This is not actually used to detect the pump angle, but serves as a good example of feature detection.  In a more complex scene, you could use OpenCV’s Region Of Interest (ROI) feature to limit further processing to only features inside this pump housing circle.</p>
<ol>
<li><p class="first">Use the <code class="docutils literal"><span class="pre">HoughCircles</span></code> method to detect a pump housing of known size:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># detect outer pump circle</span>
<span class="n">pumpRadiusRange</span> <span class="o">=</span> <span class="p">(</span> <span class="n">PUMP_DIAMETER</span><span class="o">/</span><span class="mi">2</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="n">PUMP_DIAMETER</span><span class="o">/</span><span class="mi">2</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="n">pumpCircles</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">HoughCircles</span><span class="p">(</span><span class="n">thresh</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">HOUGH_GRADIENT</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">PUMP_DIAMETER</span><span class="p">,</span> <span class="n">param2</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">minRadius</span><span class="o">=</span><span class="n">pumpRadiusRange</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">maxRadius</span><span class="o">=</span><span class="n">pumpRadiusRange</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<ul class="simple">
<li>reference: <a class="reference external" href="https://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html#houghcircles">HoughCircles</a></li>
</ul>
</li>
<li><p class="first">Add a function to display all detected circles (above the <code class="docutils literal"><span class="pre">process_image</span></code> callback):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">plotCircles</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="n">circles</span><span class="p">,</span> <span class="n">color</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">circles</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">r</span><span class="p">)</span> <span class="ow">in</span> <span class="n">circles</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="n">cv2</span><span class="o">.</span><span class="n">circle</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">)),</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">),</span> <span class="n">color</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Below the circle-detect, call the display function and check for the expected # of circles (1)</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">plotCircles</span><span class="p">(</span><span class="n">drawImg</span><span class="p">,</span> <span class="n">pumpCircles</span><span class="p">,</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pumpCircles</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">):</span>
    <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;No pump circles found!&quot;</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">pumpCircles</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">&lt;&gt;</span><span class="mi">1</span><span class="p">:</span>
    <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Wrong # of pump circles: found {} expected {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">pumpCircles</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="mi">1</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">pumpCircle</span> <span class="o">=</span> <span class="n">pumpCircles</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
</div>
</li>
<li><p class="first">Run the node and see the detected circles.</p>
<ul class="simple">
<li>Experiment with adjusting the <code class="docutils literal"><span class="pre">param2</span></code> input to <code class="docutils literal"><span class="pre">HoughCircles</span></code> to find a value that seems to work well.  This parameter represents the sensitivity of the detector; lower values detect more circles, but also will return more false-positives.</li>
<li>Tru removing the <code class="docutils literal"><span class="pre">min/maxRadius</span></code> parameters or reducing the minimum distance between circles (4th parameter) to see what other circles are detected.</li>
<li>I found that a value of <code class="docutils literal"><span class="pre">param2=7</span></code> seemed to work well</li>
</ul>
</li>
</ol>
</li>
<li><p class="first">Detect the piston sleeves, using blob detection.</p>
<p>Blob detection analyses the image to identify connected regions (blobs) of similar color.  Filtering of the resulting blob features on size, shape, or other characteristics can help identify features of interest.  We will be using OpenCV’s <a class="reference external" href="https://docs.opencv.org/3.2.0/d0/d7a/classcv_1_1SimpleBlobDetector.html">SimpleBlobDetector</a>.</p>
<ol>
<li><p class="first">Add the following code to run blob detection on the binary image:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># detect blobs inside pump body</span>
<span class="n">pistonArea</span> <span class="o">=</span> <span class="mf">3.14159</span> <span class="o">*</span> <span class="n">PISTON_DIAMETER</span><span class="o">**</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">4</span>
<span class="n">blobParams</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">SimpleBlobDetector_Params</span><span class="p">()</span>
<span class="n">blobParams</span><span class="o">.</span><span class="n">filterByArea</span> <span class="o">=</span> <span class="bp">True</span><span class="p">;</span>
<span class="n">blobParams</span><span class="o">.</span><span class="n">minArea</span> <span class="o">=</span> <span class="mf">0.80</span> <span class="o">*</span> <span class="n">pistonArea</span><span class="p">;</span>
<span class="n">blobParams</span><span class="o">.</span><span class="n">maxArea</span> <span class="o">=</span> <span class="mf">1.20</span> <span class="o">*</span> <span class="n">pistonArea</span><span class="p">;</span>
<span class="n">blobDetector</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">SimpleBlobDetector_create</span><span class="p">(</span><span class="n">blobParams</span><span class="p">)</span>
<span class="n">blobs</span> <span class="o">=</span> <span class="n">blobDetector</span><span class="o">.</span><span class="n">detect</span><span class="p">(</span><span class="n">thresh</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>Note the use of an Area filter to select blobs within 20% of the expected piston-sleeve area.</li>
<li>By default, the blob detector is configured to detect black blobs on a white background. so no additional color filtering is required.</li>
</ul>
</li>
<li><p class="first">Below the blob detection, call the OpenCV blob display function and check for the expected # of piston sleeves (7):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">drawImg</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">drawKeypoints</span><span class="p">(</span><span class="n">drawImg</span><span class="p">,</span> <span class="n">blobs</span><span class="p">,</span> <span class="p">(),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="n">cv2</span><span class="o">.</span><span class="n">DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">blobs</span><span class="p">)</span> <span class="o">&lt;&gt;</span> <span class="n">PISTON_COUNT</span><span class="p">:</span>
    <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Wring # of pistons: found {} expected {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">blobs</span><span class="p">),</span> <span class="n">PISTON_COUNT</span><span class="p">))</span>
<span class="n">pistonCenters</span> <span class="o">=</span> <span class="p">[(</span><span class="nb">int</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">pt</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span><span class="nb">int</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">pt</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">blobs</span><span class="p">]</span>
</pre></div>
</div>
</li>
<li><p class="first">Run the node and see if all piston sleeves were properly identified</p>
</li>
</ol>
</li>
<li><p class="first">Detect the primary axis of the pump body.</p>
<p>This axis is used to identify the key piston sleeve feature.  We’ll reduce the image to contours (outlines), then find the largest one, fit a rectangular box (rotated for best-fit), and identify the major axis of that box.</p>
<ol>
<li><p class="first">Calculate image contours and select the one with the largest area:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># determine primary axis, using largest contour</span>
<span class="n">im2</span><span class="p">,</span> <span class="n">contours</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">findContours</span><span class="p">(</span><span class="n">thresh</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">RETR_TREE</span><span class="p">,</span> <span class="n">cv2</span><span class="o">.</span><span class="n">CHAIN_APPROX_SIMPLE</span><span class="p">)</span>
<span class="n">maxC</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">contours</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">c</span><span class="p">:</span> <span class="n">cv2</span><span class="o">.</span><span class="n">contourArea</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li><p class="first">Fit a bounding box to the largest contour:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">boundRect</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">minAreaRect</span><span class="p">(</span><span class="n">maxC</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Copy these 3 helper functions to calculate the endpoints of the rectangle’s major axis (above the <code class="docutils literal"><span class="pre">process_image</span></code> callback):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">math</span>
<span class="o">...</span>

<span class="k">def</span> <span class="nf">ptDist</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">):</span>
    <span class="n">dx</span><span class="o">=</span><span class="n">p2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">p1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="n">dy</span><span class="o">=</span><span class="n">p2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="n">p1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">math</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span> <span class="n">dx</span><span class="o">*</span><span class="n">dx</span> <span class="o">+</span> <span class="n">dy</span><span class="o">*</span><span class="n">dy</span> <span class="p">)</span>

<span class="k">def</span> <span class="nf">ptMean</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">((</span><span class="nb">int</span><span class="p">(</span><span class="n">p1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">p2</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">p1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">p2</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">/</span><span class="mi">2</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">rect2centerline</span><span class="p">(</span><span class="n">rect</span><span class="p">):</span>
    <span class="n">p0</span><span class="o">=</span><span class="n">rect</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="n">p1</span><span class="o">=</span><span class="n">rect</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="n">p2</span><span class="o">=</span><span class="n">rect</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span> <span class="n">p3</span><span class="o">=</span><span class="n">rect</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
    <span class="n">width</span><span class="o">=</span><span class="n">ptDist</span><span class="p">(</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="p">);</span> <span class="n">height</span><span class="o">=</span><span class="n">ptDist</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span><span class="n">p2</span><span class="p">);</span>

    <span class="c1"># centerline lies along longest median</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">height</span> <span class="o">&gt;</span> <span class="n">width</span><span class="p">):</span>
        <span class="n">cl</span> <span class="o">=</span> <span class="p">(</span> <span class="n">ptMean</span><span class="p">(</span><span class="n">p0</span><span class="p">,</span><span class="n">p1</span><span class="p">),</span> <span class="n">ptMean</span><span class="p">(</span><span class="n">p2</span><span class="p">,</span><span class="n">p3</span><span class="p">)</span> <span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">cl</span> <span class="o">=</span> <span class="p">(</span> <span class="n">ptMean</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span><span class="n">p2</span><span class="p">),</span> <span class="n">ptMean</span><span class="p">(</span><span class="n">p3</span><span class="p">,</span><span class="n">p0</span><span class="p">)</span> <span class="p">)</span>

    <span class="k">return</span> <span class="n">cl</span>
</pre></div>
</div>
</li>
<li><p class="first">Call the <code class="docutils literal"><span class="pre">rect2centerline</span></code> function from above, with the bounding rectangle calculated earlier.  Draw the centerline on top of our display image.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">centerline</span> <span class="o">=</span> <span class="n">rect2centerline</span><span class="p">(</span><span class="n">cv2</span><span class="o">.</span><span class="n">boxPoints</span><span class="p">(</span><span class="n">boundRect</span><span class="p">))</span>
<span class="n">cv2</span><span class="o">.</span><span class="n">line</span><span class="p">(</span><span class="n">drawImg</span><span class="p">,</span> <span class="n">centerline</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">centerline</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">))</span>
</pre></div>
</div>
</li>
</ol>
</li>
<li><p class="first">The final step is to identify the key piston sleeve (closest to centerline) and use position to calculate the pump angle.</p>
<ol>
<li><p class="first">Add a helper function to calculate the distance between a point and the centerline:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">ptLineDist</span><span class="p">(</span><span class="n">pt</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
    <span class="n">x0</span><span class="o">=</span><span class="n">pt</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="n">x1</span><span class="o">=</span><span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span> <span class="n">x2</span><span class="o">=</span><span class="n">line</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
    <span class="n">y0</span><span class="o">=</span><span class="n">pt</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="n">y1</span><span class="o">=</span><span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span> <span class="n">y2</span><span class="o">=</span><span class="n">line</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
    <span class="k">return</span> <span class="nb">abs</span><span class="p">((</span><span class="n">x2</span><span class="o">-</span><span class="n">x1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">y1</span><span class="o">-</span><span class="n">y0</span><span class="p">)</span><span class="o">-</span><span class="p">(</span><span class="n">x1</span><span class="o">-</span><span class="n">x0</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">y2</span><span class="o">-</span><span class="n">y1</span><span class="p">))</span><span class="o">/</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">sqrt</span><span class="p">((</span><span class="n">x2</span><span class="o">-</span><span class="n">x1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x2</span><span class="o">-</span><span class="n">x1</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">y2</span><span class="o">-</span><span class="n">y1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">y2</span><span class="o">-</span><span class="n">y1</span><span class="p">)))</span>
</pre></div>
</div>
</li>
<li><p class="first">Call the <code class="docutils literal"><span class="pre">ptLineDist</span></code> function to find which piston blob is closest to the centerline.  Update the drawImg to show which blob was identified.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># find closest piston to primary axis</span>
<span class="n">closestPiston</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span> <span class="n">pistonCenters</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">ctr</span><span class="p">:</span> <span class="n">ptLineDist</span><span class="p">(</span><span class="n">ctr</span><span class="p">,</span> <span class="n">centerline</span><span class="p">))</span>
<span class="n">cv2</span><span class="o">.</span><span class="n">circle</span><span class="p">(</span><span class="n">drawImg</span><span class="p">,</span> <span class="n">closestPiston</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Calculate the angle between the 3 key points: piston sleeve centerpoint, pump center, and an arbitrary point along the horizontal axis (our reference “zero” position).</p>
<ol>
<li><p class="first">Add a helper function <code class="docutils literal"><span class="pre">findAngle</span></code> to calculate the angle between 3 points:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">numpy</span> <span class="kn">as</span> <span class="nn">np</span>

<span class="k">def</span> <span class="nf">findAngle</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p3</span><span class="p">):</span>
    <span class="n">p1</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">p1</span><span class="p">);</span> <span class="n">p2</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">p2</span><span class="p">);</span> <span class="n">p3</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">p3</span><span class="p">);</span>
    <span class="n">v1</span><span class="o">=</span><span class="n">p1</span><span class="o">-</span><span class="n">p2</span><span class="p">;</span> <span class="n">v2</span><span class="o">=</span><span class="n">p3</span><span class="o">-</span><span class="n">p2</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">math</span><span class="o">.</span><span class="n">atan2</span><span class="p">(</span><span class="o">-</span><span class="n">v1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">v2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">v1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">*</span><span class="n">v2</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">v1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">v2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">v1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">*</span><span class="n">v2</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">*</span> <span class="mi">180</span><span class="o">/</span><span class="mf">3.14159</span>
</pre></div>
</div>
</li>
<li><p class="first">Call the <code class="docutils literal"><span class="pre">findAngle</span></code> function with the appropriate 3 keypoints:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c1"># calculate pump angle</span>
<span class="n">p1</span> <span class="o">=</span> <span class="p">(</span><span class="n">orig</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">pumpCircle</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">p2</span> <span class="o">=</span> <span class="p">(</span><span class="n">pumpCircle</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">pumpCircle</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">p3</span> <span class="o">=</span> <span class="p">(</span><span class="n">closestPiston</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">closestPiston</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">angle</span> <span class="o">=</span> <span class="n">findAngle</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">p3</span><span class="p">)</span>
<span class="k">print</span> <span class="s2">&quot;Found pump angle: {}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">angle</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ol>
</li>
</ol>
</li>
<li><p class="first">You’re done!  Run the node as before.  The reported pump angle should be near 24 degrees.</p>
</li>
</ol>
</div>
<div class="section" id="challenge-exercises">
<span id="challenge-exercises"></span><h3>Challenge Exercises<a class="headerlink" href="#challenge-exercises" title="Permalink to this headline">¶</a></h3>
<p>For a greater challenge, try the following suggestions to modify the operation of this image-processing example:</p>
<ol>
<li><p class="first">Modify the <code class="docutils literal"><span class="pre">image_pub</span></code> node to rotate the image by 10 degrees between each publishing step.  The following code can be used to rotate an image:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">rotateImg</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="n">angle</span><span class="p">):</span>
    <span class="n">rows</span><span class="p">,</span><span class="n">cols</span><span class="p">,</span><span class="n">ch</span> <span class="o">=</span> <span class="n">img</span><span class="o">.</span><span class="n">shape</span>
    <span class="n">M</span> <span class="o">=</span> <span class="n">cv2</span><span class="o">.</span><span class="n">getRotationMatrix2D</span><span class="p">((</span><span class="n">cols</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span><span class="n">rows</span><span class="o">/</span><span class="mi">2</span><span class="p">),</span><span class="n">angle</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">cv2</span><span class="o">.</span><span class="n">warpAffine</span><span class="p">(</span><span class="n">img</span><span class="p">,</span><span class="n">M</span><span class="p">,(</span><span class="n">cols</span><span class="p">,</span><span class="n">rows</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li><p class="first">Change the <code class="docutils literal"><span class="pre">detect_pump</span></code> node to provide a <strong>service</strong> that performs the image detection.  Define a custom service type that takes an input image and outputs the pump angle.  Create a new application node that subscribes to the <code class="docutils literal"><span class="pre">image</span></code> topic and calls the <code class="docutils literal"><span class="pre">detect_pump</span></code> service.</p>
</li>
<li><p class="first">Try using <code class="docutils literal"><span class="pre">HoughCircles</span></code> instead of <code class="docutils literal"><span class="pre">BlobDetector</span></code> to locate the piston sleeves.</p>
</li>
</ol>
</div>
</div>
</div>


            
            <div class="admonition note">
              <p class="first admonition-title">Open Source Feedback</p>
              <p class="last">See something that needs improvement? Please open a pull request on this <a href="https://github.com/ros-industrial/industrial_training/blob/kinetic/gh_pages/_source/session5/OpenCV-in-Python.md" class="fa fa-github"> GitHub page</a></p>
            </div>
            
           </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../session6/Documentation-Generation.html" class="btn btn-neutral float-right" title="Documentation Generation" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="Simple-PCL-Interface-for-Python.html" class="btn btn-neutral" title="Building a Simple PCL Interface for Python" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div class="footer-override">
    <a href="http://rosindustrial.org/ric">
      <img src="../../_static/footer.jpg"/>
    </a>
  </div>

  <div role="contentinfo">
    <p>
    </p>
  </div>
  Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.

</footer>
        </div>
      </div>

    </section>

  </div>
  <script>
  var pre = document.getElementsByTagName('pre');
  for (var i = 0; i < pre.length; i++) {
    var button = document.createElement('button');
    button.className = 'btn-copyboard fa fa-copy btn';
    pre[i].before(button);
  }

  var clipboard = new Clipboard('.btn-copyboard', {
    target: function(trigger) {return trigger.nextElementSibling;}
  });

  function showSuccess(elem){elem.setAttribute('class','btn-copyboard fa fa-check btn');}
  function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
  }
  clipboard.on('success',function(e){
    showSuccess(e.trigger);
    sleep(350).then(() => {e.clearSelection();
      e.trigger.setAttribute('class','btn-copyboard fa fa-copy btn');})
  });
  </script>

  
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
        <span class="fa fa-book"> Other Versions</span>
        v: kinetic
        <span class="fa fa-caret-down"></span>
    </span>
    <div class="rst-other-versions">
        <dl>
            <dt>Branches</dt>
            <dd><a href="../../kinetic/_source/session5/OpenCV-in-Python.html">kinetic</a></dd>
        </dl>
    </div>
</div>


  

    <script type="text/javascript">
        var DOCUMENTATION_OPTIONS = {
            URL_ROOT:'../../',
            VERSION:'',
            COLLAPSE_INDEX:false,
            FILE_SUFFIX:'.html',
            HAS_SOURCE:  true,
            SOURCELINK_SUFFIX: '.txt'
        };
    </script>
      <script type="text/javascript" src="../../_static/jquery.js"></script>
      <script type="text/javascript" src="../../_static/underscore.js"></script>
      <script type="text/javascript" src="../../_static/doctools.js"></script>

  

  
  
    <script type="text/javascript" src="../../_static/js/theme.js"></script>
  

  
  
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.StickyNav.enable();
      });
  </script>
   

</body>
</html>